package com.hanxiaozhang.redis;

import com.hanxiaozhang.AbstractDistributedLock;
import com.hanxiaozhang.exception.DistributedLockException;
import org.redisson.api.RedissonClient;

import java.util.concurrent.TimeUnit;

/**
 * 〈一句话功能简述〉<br>
 * 〈Redis分布式锁〉
 * <p>
 * 底层类：RedissonLock
 *
 * @author hanxinghua
 * @create 2022/9/3
 * @since 1.0.0
 */
public class RedisDistributedLock extends AbstractDistributedLock {

    private RedissonClient client;

    public RedisDistributedLock(String lockKey, RedissonClient client) {
        super.lockKey = lockKey;
        this.client = client;
    }

    @Override
    public void lock() throws DistributedLockException {
        try {
            client.getLock(lockKey).lock();
        } catch (Exception e) {
            throw new DistributedLockException("lockKey是 " + lockKey + " 加锁异常: ", e);
        }
    }


    /**
     * 加锁以后，在leaseTime之后自动解锁，除非在leaseTime之前调用unlock解锁
     * Redisson特有的方法
     *
     * @param leaseTime 租期
     * @param unit
     * @throws DistributedLockException
     */
    public void lock(long leaseTime, TimeUnit unit) throws DistributedLockException {
        try {
            client.getLock(lockKey).lock(leaseTime, unit);
        } catch (Exception e) {
            throw new DistributedLockException("lockKey是 " + lockKey + " 加锁异常: ", e);
        }
    }


    @Override
    public Boolean tryLock() throws DistributedLockException {
        try {
            return client.getLock(lockKey).tryLock();
        } catch (Exception e) {
            throw new DistributedLockException("lockKey是 " + lockKey + " 尝试加锁异常: ", e);
        }
    }

    @Override
    public Boolean tryLock(long time, TimeUnit timeUnit) throws DistributedLockException {
        try {
            return client.getLock(lockKey).tryLock(time, timeUnit);
        } catch (Exception e) {
            throw new DistributedLockException("lockKey是 " + lockKey + " 尝试加锁异常: ", e);
        }
    }


    /**
     * 尝试加锁，在加锁成功后，在leaseTime之后自动解锁，除非在leaseTime之前调用unlock解锁
     * Redisson特有的方法
     *
     * @param time
     * @param leaseTime
     * @param timeUnit
     * @return
     * @throws DistributedLockException
     */
    public Boolean tryLock(long time, long leaseTime, TimeUnit timeUnit) throws DistributedLockException {
        try {
            return client.getLock(lockKey).tryLock(time, leaseTime, timeUnit);
        } catch (Exception e) {
            throw new DistributedLockException("lockKey是 " + lockKey + " 尝试加锁异常: ", e);
        }
    }


    @Override
    public void unlock() throws DistributedLockException {
        try {
            client.getLock(lockKey).unlock();
        } catch (Exception e) {
            throw new DistributedLockException("lockKey是 " + lockKey + " 释放锁异常: ", e);
        }
    }

}
